/*
 *    Author: Zhenghuabin
 *   Created: Thu Jan 16 14:40:50 2014
 *
 */
#ifndef _ASIO_TASK_POOL_H_
#define _ASIO_TASK_POOL_H_
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <glog/logging.h>

namespace common {
    namespace util {

        class AsioTaskPool : private boost::noncopyable {
            typedef boost::shared_ptr<boost::thread> ThreadPtr;
      public:
      AsioTaskPool() : num_workers_(1), work_(new boost::asio::io_service::work(io_service_)) {
            }
      AsioTaskPool(size_t num_workers) : num_workers_(num_workers), 
      work_(new boost::asio::io_service::work(io_service_)) {
            }
            ~AsioTaskPool() {
                LOG(INFO) << "AsioTaskPool::~AsioTaskPool";
            }
            void start() {
                manage_thread_.reset(new boost::thread(boost::bind(&AsioTaskPool::start_, this)));
            }
            template <typename Callable>
            void post(const Callable& callable) {
                io_service_.post(callable);
            }
            void stop() {
                io_service_.stop();
            }
            void wait() {
                work_.reset();
                manage_thread_->join();
            }
            boost::asio::io_service& get_io_service() {
                return io_service_;
            }
      private:
            void start_() {
                LOG(INFO) << "task pool started";
                for (size_t i = 0; i < num_workers_; ++i) {
                    workers_.push_back(ThreadPtr(new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_))));
                }
                for (size_t i = 0; i < num_workers_; ++i) {
                    workers_[i]->join();
                }
                LOG(INFO) << "task pool stoped";
            }
      private:
            size_t num_workers_;
            boost::asio::io_service io_service_;
            boost::scoped_ptr<boost::asio::io_service::work> work_;
            std::vector<ThreadPtr> workers_;
            ThreadPtr manage_thread_;
        };
    }
}
#endif /*_ASIO_TASK_POOL_H_*/
